package List中的流式编程;

import java.util.*;
import java.util.stream.Collectors;

public class List中的流式编程
{
    static class Employee {
        private String name;
        private String department;
        private double salary;
        private int age;

        public Employee(String name, String department, double salary, int age) {
            this.name = name;
            this.department = department;
            this.salary = salary;
            this.age = age;
        }

        // Getters
        public String getName() { return name; }
        public String getDepartment() { return department; }
        public double getSalary() { return salary; }
        public int getAge() { return age; }

        @Override
        public String toString() {
            return name + "(" + department + ")";
        }
    }
    public static void main(String[] args){
        // 创建测试数据
        List<Employee> employees = Arrays.asList(
                new Employee("张三", "技术部", 12000, 28),
                new Employee("李四", "市场部", 8500, 25),
                new Employee("王五", "技术部", 15000, 32),
                new Employee("赵六", "财务部", 7800, 35),
                new Employee("钱七", "市场部", 9200, 26),
                new Employee("孙八", "技术部", 11000, 30),
                new Employee("周九", "财务部", 6500, 22),
                new Employee("吴十", "技术部", 15000, 28)  // 相同薪资测试
        );

        // 1. 数据过滤：筛选薪资>8000的员工
        List<Employee> highSalaryEmployees = employees.stream()
                .filter(e -> e.getSalary() > 8000)
                .collect(Collectors.toList());
        System.out.println("高薪员工: " + highSalaryEmployees);

        // 2. 数据转换：提取所有员工姓名
        List<String> names = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        System.out.println("\n所有员工姓名: " + names);

        // 3. 数据聚合：计算薪资总和
        double totalSalary = employees.stream()
                .mapToDouble(Employee::getSalary)
                .sum();
        System.out.println("\n总薪资支出: " + totalSalary);

        // 4. 分组统计：按部门统计员工数
        Map<String, Long> deptCount = employees.stream()
                .collect(Collectors.groupingBy(
                        Employee::getDepartment,
                        Collectors.counting()
                ));
        System.out.println("\n部门人数统计: " + deptCount);

        // 5. 多级分组：按部门和薪资级别分组
        Map<String, Map<String, List<Employee>>> multiGroup = employees.stream()
                .collect(Collectors.groupingBy(
                        Employee::getDepartment,
                        Collectors.groupingBy(e -> e.getSalary() > 8000 ? "高薪" : "普通")
                ));
        System.out.println("\n部门薪资分级:");
        multiGroup.forEach((dept, salMap) -> {
            System.out.println(dept + ":");
            salMap.forEach((level, list) ->
                                   System.out.println("  " + level + " -> " + list)
            );
        });

        // 6. 排序：按年龄降序，薪资升序
        List<Employee> sorted = employees.stream()
                .sorted(Comparator
                                .comparing(Employee::getAge).reversed()
                                .thenComparing(Employee::getSalary)
                )
                .collect(Collectors.toList());
        System.out.println("\n排序结果(年龄降序，薪资升序): " + sorted);

        // 7. 去重：获取不重复部门
        List<String> distinctDepts = employees.stream()
                .map(Employee::getDepartment)
                .distinct()
                .collect(Collectors.toList());
        System.out.println("\n不重复部门: " + distinctDepts);

        // 8. 分页查询：每页3条，取第2页
        List<Employee> page = employees.stream()
                .skip(3)  // 跳过第1页的3条
                .limit(3) // 取第2页的3条
                .collect(Collectors.toList());
        System.out.println("\n分页结果(第2页): " + page);

        // 9. 并行处理：计算平均薪资
        double avgSalary = employees.parallelStream()
                .mapToDouble(Employee::getSalary)
                .average()
                .orElse(0);
        System.out.println("\n平均薪资(并行计算): " + avgSalary);

        // 10. 匹配检查：是否有未满25岁的员工
        boolean hasYoung = employees.stream()
                .anyMatch(e -> e.getAge() < 25);
        System.out.println("\n是否有年轻员工(<25岁): " + hasYoung);

        // 11. 数据拼接：部门名称拼接
        String deptString = employees.stream()
                .map(Employee::getDepartment)
                .distinct()
                .collect(Collectors.joining(" > "));
        System.out.println("\n部门名称链: " + deptString);

        // 12. 统计摘要：薪资统计
        DoubleSummaryStatistics stats = employees.stream()
                .mapToDouble(Employee::getSalary)
                .summaryStatistics();
        System.out.println("\n薪资统计:");
        System.out.println("  最高: " + stats.getMax());
        System.out.println("  最低: " + stats.getMin());
        System.out.println("  平均: " + stats.getAverage());
        System.out.println("  总和: " + stats.getSum());

        // 13. 找出最高薪资员工（新增）
        // 方式1：使用max()直接获取
        Optional<Employee> topEarner = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));

        // 方式2：使用reduce比较获取
        Optional<Employee> topEarner2 = employees.stream()
                .reduce((e1, e2) -> e1.getSalary() > e2.getSalary() ? e1 : e2);

        // 处理可能有多个最高薪资的情况
        double maxSalary = employees.stream()
                .mapToDouble(Employee::getSalary)
                .max()
                .orElse(0);

        List<Employee> topEarners = employees.stream()
                .filter(e -> e.getSalary() == maxSalary)
                .collect(Collectors.toList());

        System.out.println("\n最高薪资员工: " + topEarners);
        System.out.println("最高薪资: " + maxSalary);
    }

}
